/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package controller;

import ServerSide.database;
import com.sun.xml.internal.ws.developer.ServerSideException;
import helper.Connect;
import helper.Protocol;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import model.WorkingDirectory;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 *
 * @author LegACy
 */
public class Responder implements Runnable {

    private String Repository;

    public Responder() {
        //Initialize
        m_Running = true;
        m_Connections = new ArrayList<Socket>();
    }

    public void addConnection(Socket connection) {
        //Add connection to the list
        m_Connections.add(connection);
    }

    public void run() {
        //While running
        while (m_Running) {
            //Sleep for a bit
            try {
                Thread.sleep(50);
            } catch (InterruptedException ex) {
            }

            //Check for any new connection
            if (!m_Connections.isEmpty()) {
                //Get new connection
                Socket Processed = m_Connections.get(0);
                m_Connections.remove(Processed);

                try {
                    //Send message
                    PrintWriter Writer = new PrintWriter(Processed.getOutputStream());
                    Writer.println(createResponse(Processed));
                    Writer.flush();

                    //Close
                    Writer.close();
                    Processed.close();
                } catch (IOException ex) {
                }
            }
        }
    }

    protected String createResponse(Socket connection) throws IOException {
        //Variable
        String Result = "";

        //Create reader
        BufferedReader Reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));

        try {
            //Read conection
            int Action = Reader.read();
            JSONObject Request = new JSONObject(Reader.readLine());

            //Based on action
            Result += (char) (Action + Protocol.RESPONSE_OFFSET);
            switch (Action) {
                case Protocol.ACTION_LOGIN:
                    Result += processLogin(Request.getString("username"), Request.getString("password"));
                    break;
                case Protocol.ACTION_LATEST:
                    Result += processLatest(Request.getString("username"));
                    break;
                case Protocol.ACTION_STRUCTURE:
                    Result += processStructure(Request.getString("username"), Request.getInt("version"));
                    break;
                case Protocol.ACTION_STRUCTURE_UP:
                    Result += processStructureUpload(Request.getString("username"), Request.getJSONArray("directories"));
                    break;
                default:
                    Result = "" + (char) 0;
            }
        } catch (JSONException ex) {
            Result = "" + (char) Protocol.ACTION_NONE;
        }


        //Return result
        return Result;
    }

    protected String processLogin(String username, String password) throws JSONException {
        
        ServerSide.Server.addtoLog(username+" request login");
        //Check with database
        boolean Login = false;
        try {
            Login = database.CheckUser(username, password);
        } catch (SQLException ex) {
        }

        //Create JSON
        JSONObject Result = new JSONObject();

        //Save data to json
        Result.put("result", Login);
        if (!Login) {
            Result.put("reason", "Username and password don't match");
        }
        return Result.toString();
    }

    protected String processLatest(String username) throws JSONException {

        ServerSide.Server.addtoLog(username+" request headrevision");
        //Get latest
        int Latest = -1;
        try {
            Latest = database.GetHeadRevision(username);
        } catch (SQLException ex) {
        }

        //Create JSON
        JSONObject Result = new JSONObject();

        //Save data to json
        if (Latest >= 0) {
            Result.put("result", true);
            Result.put("latest", Latest);
        } else {
            Result.put("result", false);
            Result.put("reason", "Error connecting to database");
        }

        //Return as string
        return Result.toString();
    }

    protected String processStructure(String username, int version) throws JSONException {

        ServerSide.Server.addtoLog(username+" request version "+ version);
        //Create JSON
        JSONObject Result = new JSONObject();

        //Get structure
        ArrayList<WorkingDirectory> Directories = new ArrayList<WorkingDirectory>();
        Directories = ControllerWD.WDserverMaker(Repository, username, version);
        
        //Create json array
        JSONArray DirectoriesJSON = new JSONArray();
        for (int i = 0; i < Directories.size(); i++) {
            DirectoriesJSON.put(Directories.get(i).getJSON());
        }

        //Save data to json
        Result.put("result", true);
        Result.put("directories", DirectoriesJSON);
        return Result.toString();
    }

    protected String processStructureUpload(String username, JSONArray structure) throws JSONException {

        ServerSide.Server.addtoLog(username+" syncornized");
        //Create JSON
        JSONObject Result = new JSONObject();

        //Create directory list
        ArrayList<WorkingDirectory> Directories = new ArrayList<WorkingDirectory>();
        for (int i = 0; i < structure.length(); i++) {
            Directories.add(new WorkingDirectory(structure.getJSONObject(i)));
        }
        try {
            //Increment revision
            database.IncreaseRevision(username);
            ControllerWD.WDserverWriter(Directories, Repository, username, database.GetHeadRevision(username));
        } catch (SQLException ex) {
            Logger.getLogger(Responder.class.getName()).log(Level.SEVERE, null, ex);
        }
        //Save data to json
        Result.put("result", true);
        return Result.toString();
    }
    //Members
    protected boolean m_Running;
    protected ArrayList<Socket> m_Connections;

    /**
     * @param Repository the Repository to set
     */
    public void setRepository(String Repository) {
        this.Repository = Repository;
    }
}
